Skip to content

TCP

传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议

TCP 三次握手

目的

为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建立虚连接。

具体步骤

TCP三次握手

SYN

同步序列编号(Synchronize Sequence Numbers)。是 TCP/IP 建立连接时使用的握手信号。是 TCP 连接的第一个包,非常小的一种数据包。

ACK

确认字符 (Acknowledge character)。在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误。在 TCP/IP 协议中,如果接收方成功的接收到数据,那么会回复一个 ACK 数据。通常 ACK 信号有自己固定的格式,长度大小,由接收方回复给发送方。

seq

是数据包本身的序列号

ack

是对收到的数据包的确认,值是下次希望接收的数据包的序列号。

第一次握手

客户端向服务端发送连接请求报文段。该报文段的头部中 SYN=1,ACK=0,同时选择一个初始序号 seq=x。请求发送后,客户端便进入SYN-SENT 状态。

第二次握手

服务端收到连接请求报文段后,如果同意连接,会发送一个应答:SYN=1,ACK=1,seq=y,ack=x+1。发送完应答后服务端进入SYN-RCVD 状态。

第三次握手

客户端收到服务端连接同意的应答后,还会向服务端发送一个确认报文段,表示:服务端发来的连接同意应答已经成功收到。该报文段的头部为:ACK=1,seq=x+1,ack=y+1。该报文发送完毕后,客户端和服务器端都进入 ESTABLISHED 状态,完成 TCP 三次握手。

常见问题

Q1. 为什么要握三次,而不是两次或四次?

首先非常明确的是两次握手是最基本的。三次握手是为了防止已失效的连接请求报文段突然又传送到了服务端,造成服务端资源的浪费。不是四次握手:因为三次握手已经能说明握手时的通信是正常的,四次握手、五次握手就显得浪费了。

  • 第一次握手,客户端发了个连接请求消息到服务端,服务端收到信息后知道自己与客户端是可以连接成功的,但此时客户端并不知道服务端是否已经接收到了它的请求。
  • 第二次握手,服务端接收到消息后的应答,客户端得到服务端的反馈后,才确定自己与服务端是可以连接上的, 客户端只有确定了自己能与服务端连接上才能开始发数据。所以两次握手肯定是最基本的。
  • 第三次握手,是为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误。譬如发起请求遇到类似这样的情况:客户端发出去的第一个连接请求由于某些原因在网络节点中滞留了导致延迟,直到连接释放的某个时间点才到达服务端,这是一个早已失效的报文,但是此时服务端仍然认为这是客户端的建立连接请求第一次握手,于是服务端回应了客户端,第二次握手。如果只有两次握手,那么到这里,连接就建立了,但是此时客户端并没有任何数据要发送,而服务端还在傻傻的等候佳音,造成很大的资源浪费。所以需要第三次握手,只有客户端再次回应一下,就可以避免这种情况。

Q2. 如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP 还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为 2 小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔 75 秒钟发送一次。若一连发送 10个 探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

TCP 四次挥手

TCP连接是双向的,在四次挥手中,前两次挥手用于断开一个方向的连接,后两次挥手用于断开另一方向的连接。

TCP四次挥手

第一次挥手

客户端数据发送完成,则它向服务端发送连接释放请求。该请求只有报文头,头中携带的主要参数为:FIN=1,seq=u。此时,客户端将进入 FIN-WAIT-1 状态。TCP 规定,FIN 报文段即使不携带数据,也要消耗一个序号。

第二次挥手

服务器收到客户端连接释放报文,通知相应的高层应用进程,告诉它客户端向服务器这个方向的连接已经释放了。此时服务端进入了CLOSE-WAIT(关闭等待)状态,并向客户端发出连接释放的应答,其报文头包含:ACK=1,ack=u+1,seq=v。

客户端收到该应答后,进入FIN-WAIT-2状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

第二次挥手完成后,客户端到服务端方向的连接已经释放,服务端不会再接收客户端的数据,客户端也没有数据要发送了。但服务端到客户端方向的连接仍然存在,服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。

第三次挥手

服务端将最后的数据发送完毕后,就向客户端发送连接释放报文,其报文头包含:FIN=1,ack=u+1,由于在 CLOS-WAIT 状态,服务端很可能又发送了一些数据,假定此时的序列号为 seq=w,此时,服务器就进入了 LAST-ACK(最后确认)状态,等待客户端的确认。

第四次挥手

客户端收到服务器的连接释放报文后,向服务端发出确认应答,报文头:ACK=1,ack=w+1,seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。该状态会持续 2MSL(最长报文段寿命)时间,这个期间 TCP 连接还未释放,若该时间段内没有服务端的重发请求的话,客户端就进入 CLOSED 状态,服务端只要收到了客户端发出的确认,立即进入 CLOSED 状态。就结束了这次的 TCP 连接。可以看到,服务器结束 TCP 连接的时间要比客户端早一些。

TCP 与 UDP

  • TCP 面向连接(TCP 三次握手),UDP 是无连接的,即发送数据之前不需要建立连接。
  • 每一条 TCP 连接只能是点到点的;UDP 支持一对一,一对多,多对一和多对多的交互通信。
  • TCP 面向字节流,实际上是 TCP 把数据看成一连串无结构的字节流;UDP是面向报文的。
  • TCP 有序,UDP 无序;消息在传输过程中可能会乱序,后发送的消息可能会先到达,TCP 会对其进行重排序,UDP不会。
  • TCP 有流量控制(拥塞控制),UDP 没有。
  • TCP 传输速率慢,由于传输要进行三次握手,以及会进行拥塞控制等。
  • TCP 应用场景:效率要求相对低,但对准确性要求相对高的场景。因为传输中需要对数据确认、重发、排序等操作,相比之下效率没有UDP 高。举几个例子:文件传输(准确高要求高、但是速度可以相对慢)、接受邮件、远程登录。UDP 应用场景:效率要求相对高,对准确性要求相对低的场景。举几个例子:QQ 聊天、在线视频、网络语音电话(即时通讯,速度要求高,但是出现偶尔断续不是太大问题,并且此处完全不可以使用重发机制)、广播通信(广播、多播)。
TCPUDP
连接面向连接无连接
连接方式点到点支持一对一,一对多,多对一和多对多
模式流模式(TCP)数据报模式(UDP)
头部大小20字节8字节
有序性有序无序
传输速率控制流量控制(拥塞控制)
可靠性可靠不可靠
传输速率
占用系统资源
应用场景效率要求相对低,但对准确性要求相对高的场景。效率要求相对高,对准确性要求相对低的场景